package com.study.flink.word;

import org.apache.flink.api.common.functions.FlatMapFunction;
import org.apache.flink.api.java.utils.ParameterTool;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.windowing.time.Time;
import org.apache.flink.util.Collector;

/**
 * 流处理
 * @author: stephen.shen
 * @create: 2019-01-25 13:35
 * Socket启动命令： nc -l 1234
 */
public class JavaStreamWordCount {

    public static void main(String[] args) throws Exception {
        final String hostname ;
        final int port;
        final String delimiter = "\n";

        try {
            final ParameterTool params = ParameterTool.fromArgs(args);
            port = params.getInt("port",1234);
            hostname = params.get("hostname","127.0.0.1") ;
        } catch (Exception e) {
            System.err.println("No port specified. Please run 'JavaWordCount --hostname <hostname> --port <port>'");
            return;
        }

        // 获取execution environment,
        final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

        // 连接socket获取输入的数据
        DataStream<String> text = env.socketTextStream(hostname, port, delimiter);

        //计算数据
        DataStream<WordWithCount> windowCount = text.flatMap(new FlatMapFunction<String, WordWithCount>() {
            @Override
            public void flatMap(String value, Collector<WordWithCount> out) throws Exception {
                String[] splits = value.split("\\s");
                for (String word : splits) {
                    out.collect(new WordWithCount(word, 1L));
                }
            }
        })
                //打平操作，把每行的单词转为<word,count>类型的数据
                .keyBy("word")
                //指定计算数据的窗口大小和滑动窗口大小
                .timeWindow(Time.seconds(2), Time.seconds(1))
                .sum("count");

        //把数据打印到控制台
        windowCount.print()
                //使用一个并行度
                .setParallelism(1);
        //注意：因为flink是懒加载的，所以必须调用execute方法，上面的代码才会执行
        env.execute("Socket window count by java");
    }


    /**
     * 主要为了存储单词以及单词出现的次数
     */
    public static class WordWithCount {
        public String word;
        public long count;

        public WordWithCount() {
        }

        public WordWithCount(String word, long count) {
            this.word = word;
            this.count = count;
        }

        @Override
        public String toString() {
            return "WordWithCount{" +
                    "word='" + word + '\'' +
                    ", count=" + count +
                    '}';
        }
    }
}
